package com.uzai.console.service.wwgroup.impl;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.uzai.common.enums.DeviceTypeEnum;
import com.uzai.common.exception.BusinessException;
import com.uzai.console.dto.GroupCreateTaskDTO;
import com.uzai.console.dto.GroupCreateTaskQueryDTO;
import com.uzai.console.dto.wechatprivate.wxq.wxgroup.WxGroupCreateDto;
import com.uzai.console.dto.wechatwork.wxq.wxgroup.WxWorkGroupCreateDto;
import com.uzai.console.entity.GroupCreateTask;
import com.uzai.console.entity.GroupCreateTaskRecord;
import com.uzai.console.mapper.GroupCreateTaskMapper;
import com.uzai.console.queue.ConsoleDelayProducer;
import com.uzai.console.queue.ConsoleDelayTask;
import com.uzai.console.service.wechatprivate.WxGroupService;
import com.uzai.console.service.wechatwork.WxWorkGroupService;
import com.uzai.console.service.wwgroup.GroupCreateTaskRecordService;
import com.uzai.console.service.wwgroup.GroupCreateTaskService;
import com.uzai.console.vo.GroupCreateTaskVO;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 建群任务(GroupCreateTask)表服务实现类
 *
 * @author szl
 * @since 2024-04-23 16:29:33
 */
@Service
public class GroupCreateTaskServiceImpl extends ServiceImpl<GroupCreateTaskMapper, GroupCreateTask> implements GroupCreateTaskService {

    static final String cacheKey = "console_group_create_task_%s";

    @Autowired
    private GroupCreateTaskRecordService groupCreateTaskRecordService;
    @Autowired
    private WxWorkGroupService wxWorkGroupService;
    @Autowired
    private WxGroupService wxGroupService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Page<GroupCreateTaskVO> search(GroupCreateTaskQueryDTO query) {

        Page<GroupCreateTaskVO> result = new Page<>(query.getCurrent(), query.getSize());

        Page<GroupCreateTask> page = new Page<>(query.getCurrent(), query.getSize());
        query.convert(page);
        LambdaQueryWrapper<GroupCreateTask> condition = Wrappers.lambdaQuery(GroupCreateTask.class);
        condition.eq(GroupCreateTask::getMerId, query.getMerId());
        condition.eq(GroupCreateTask::getDeviceType, query.getDeviceType());
        page = this.getBaseMapper().selectPage(page, condition);
        List<GroupCreateTask> records = page.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return result;
        }
        List<GroupCreateTaskVO> resultRecords = records.stream().map(item -> {
            GroupCreateTaskVO vo = new GroupCreateTaskVO();
            BeanUtils.copyProperties(item, vo);
            vo.setGroupMembers(JSON.parseArray(item.getGroupMembers(), String.class));
            vo.setDeviceUniqueIds(JSON.parseArray(item.getDeviceUniqueId(), Long.class));
            return vo;
        }).collect(Collectors.toList());
        //
        return result.setRecords(resultRecords).setTotal(page.getTotal());
    }

    @Override
    public void delete(Long id) {
        GroupCreateTask createTask = this.getBaseMapper().selectById(id);
        if (Objects.isNull(createTask) || Objects.equals(createTask.getStatus(), 2)) {
            throw new BusinessException("不支持的操作");
        }
        groupCreateTaskRecordService.deleteByTaskId(createTask.getMerId(), id);
        this.getBaseMapper().deleteById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Deprecated
    public void open(Long merId, Long id) {
//        List<Long> runIds = this.getBaseMapper().selectListIdByStatus(2);
//        if (ObjectUtils.isNotEmpty(runIds)) {
//            runIds.remove(id);
//            if (ObjectUtils.isNotEmpty(runIds)) {
//                throw new BusinessException("当前已经有进行的建群任务, 不允许同时开启多个");
//            }
//        }
//        GroupCreateTask createTask = this.getBaseMapper().selectById(id);
//
//        if (Objects.isNull(createTask) || Lists.newArrayList(2, 4).contains(createTask.getStatus())) {
//            throw new BusinessException("当前任务状态不支持开启");
//        }
//        List<GroupCreateTaskRecord> taskRecords = groupCreateTaskRecordService.listByTaskId(createTask.getMerId(), createTask.getId());
//
//        GroupCreateTask update = new GroupCreateTask();
//        update.setId(createTask.getId());
//        update.setStatus(2);
//        update.setStartTime((int) (System.currentTimeMillis() / 1000L));
//        update.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
//        this.updateById(update);
//
//        if (ObjectUtils.isEmpty(taskRecords)) {
//            generateRecords(createTask);
//        }
//
//        this.execute(createTask);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void open(Long merId, Long id, Integer deviceType) {
        List<Long> runIds = this.getBaseMapper().selectListIdByStatusAndDeviceType(2, deviceType);
        if (ObjectUtils.isNotEmpty(runIds)) {
            runIds.remove(id);
            if (ObjectUtils.isNotEmpty(runIds)) {
                throw new BusinessException("当前已经有进行的建群任务, 不允许同时开启多个");
            }
        }
        GroupCreateTask createTask = this.getBaseMapper().selectById(id);

        if (Objects.isNull(createTask) || Lists.newArrayList(2, 4).contains(createTask.getStatus())) {
            throw new BusinessException("当前任务状态不支持开启");
        }
        List<GroupCreateTaskRecord> taskRecords = groupCreateTaskRecordService.listByTaskId(createTask.getMerId(), createTask.getId());

        GroupCreateTask update = new GroupCreateTask();
        update.setId(createTask.getId());
        update.setStatus(2);
        update.setStartTime((int) (System.currentTimeMillis() / 1000L));
        update.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
        this.updateById(update);

        if (ObjectUtils.isEmpty(taskRecords)) {
            generateRecords(createTask);
        }

        this.execute(createTask);
    }

    @Override
    public void pause(Long id) {
        GroupCreateTask createTask = this.getBaseMapper().selectById(id);
        if (Objects.isNull(createTask)) {
            throw new BusinessException("任务不存在");
        }
        if (!Objects.equals(createTask.getStatus(), 2)) {
            throw new BusinessException("当前任务状态不支持暂停");
        }
        GroupCreateTask update = new GroupCreateTask();

        update.setId(id);
        update.setStatus(3);
        update.setUpdateTime((int) (System.currentTimeMillis() / 1000L));

        this.updateById(update);

        List<Long> ids = groupCreateTaskRecordService.listIdsByTaskId(createTask.getMerId(), createTask.getId());
        //
        ids.forEach(ConsoleDelayProducer.instance::removeTask);
        String cacheKey = String.format(GroupCreateTaskServiceImpl.cacheKey, createTask.getId());
        redisTemplate.delete(cacheKey);
    }

    @Override
    public void end(Long id) {
        GroupCreateTask createTask = this.getBaseMapper().selectById(id);
        if (Objects.isNull(createTask)) {
            throw new BusinessException("任务不存在");
        }
        if (Objects.equals(createTask.getStatus(), 4) || Objects.equals(createTask.getStatus(), 1)) {
            throw new BusinessException("当前任务状态不支持结束");
        }
        GroupCreateTask update = new GroupCreateTask();

        update.setId(id);
        update.setStatus(4);
        update.setUpdateTime((int) (System.currentTimeMillis() / 1000L));

        this.updateById(update);

        List<Long> ids = groupCreateTaskRecordService.listIdsByTaskId(createTask.getMerId(), createTask.getId());
        //
        ids.forEach(ConsoleDelayProducer.instance::removeTask);
        String cacheKey = String.format(GroupCreateTaskServiceImpl.cacheKey, createTask.getId());
        redisTemplate.delete(cacheKey);
    }

    @Override
    public void execute(GroupCreateTask createTask) {
        Long taskId = createTask.getId();
        String cacheKey = String.format(GroupCreateTaskServiceImpl.cacheKey, taskId);
        if (Boolean.TRUE.equals(redisTemplate.hasKey(cacheKey))) {
            return;
        }
        redisTemplate.opsForValue().set(cacheKey, createTask.getId(), 1, TimeUnit.DAYS);
        List<Long> deviceUniqueIds = JSON.parseArray(createTask.getDeviceUniqueId(), Long.class);

        for (Long deviceUniqueId : deviceUniqueIds) {
            int now = (int) (System.currentTimeMillis() / 1000L);
            List<GroupCreateTaskRecord> recordList = groupCreateTaskRecordService.listByTaskId(createTask.getMerId(), taskId, deviceUniqueId);
            if (ObjectUtils.isEmpty(recordList)) {
                completeTask(createTask.getId());
                redisTemplate.delete(cacheKey);
                break;
            }
            for (GroupCreateTaskRecord record : recordList) {
                record.setDeviceType(createTask.getDeviceType());
                if (record.getPublishTime() <= now) {
                    this.doCreateGroup(record);
                    continue;
                }
                int delay = record.getPublishTime() - now;
                //
                ConsoleDelayProducer.instance.addDelayTask(
                        new ConsoleDelayTask(record.getId(), delay, "创建[" + createTask.getDeviceType() + "]群: " + record.getGroupName(), () -> this.doCreateGroup(record))
                );
            }
        }
    }

    @Override
    public Boolean add(GroupCreateTask groupCreateTask) {
        return this.getBaseMapper().insert(groupCreateTask) > 0;
    }

    @Override
    public List<GroupCreateTask> listByStatus(int i) {
        return this.getBaseMapper().selectListByStatus(i);
    }

    @Override
    public Boolean edit(GroupCreateTaskDTO param) {
        Long id = param.getId();
        GroupCreateTask byId = this.getById(id);
        if (Objects.isNull(byId)) {
            throw new BusinessException("修改失败: 任务不存在");
        }
        if (Lists.newArrayList(2, 4).contains(byId.getStatus())) {
            throw new BusinessException("修改失败, 当前任务进行中或已结束");
        }
        GroupCreateTask groupCreateTask = new GroupCreateTask();
        BeanUtils.copyProperties(param, groupCreateTask);
        groupCreateTask.setId(param.getId());
        groupCreateTask.setDeviceUniqueId(JSON.toJSONString(param.getDeviceUniqueIds()));
        groupCreateTask.setGroupMembers(JSON.toJSONString(param.getGroupMembers()));
        groupCreateTask.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
        this.updateById(groupCreateTask);
        return true;
    }

    private void doCreateGroup(GroupCreateTaskRecord record) {

        GroupCreateTaskRecord update = new GroupCreateTaskRecord();
        update.setId(record.getId());
        update.setStatus(1);
        try {
            if (record.getDeviceType().equals(DeviceTypeEnum.DT_ANDROID_WORK_WECHAT_VALUE)) {
                WxWorkGroupCreateDto wxWorkGroupCreateDto = new WxWorkGroupCreateDto();
                wxWorkGroupCreateDto.setGroupName(record.getGroupName());
                wxWorkGroupCreateDto.setMerId(record.getMerId());
                wxWorkGroupCreateDto.setDeviceUniqueId(record.getDeviceUniqueId());
                wxWorkGroupCreateDto.setMemberIdList(JSON.parseArray(record.getGroupMembers(), String.class));

                wxWorkGroupService.createWxWorkGroup(wxWorkGroupCreateDto);
            } else {
                WxGroupCreateDto wxGroupCreateDto = new WxGroupCreateDto();
                wxGroupCreateDto.setGroupName(record.getGroupName());
                wxGroupCreateDto.setMerId(record.getMerId());
                wxGroupCreateDto.setDeviceUniqueId(record.getDeviceUniqueId());
                wxGroupCreateDto.setMemberIdList(JSON.parseArray(record.getGroupMembers(), String.class));
                wxGroupService.createWxGroup(wxGroupCreateDto);
            }

            update.setUpdateTime((int) (System.currentTimeMillis() / 1000L));

            if (Objects.equals(record.getLast(), 1)) {
                this.completeTask(record.getTaskId());
            }
        } catch (Exception e) {
            log.error("doCreateGroup 执行失败", e);
            update.setRemark(ExceptionUtil.getSimpleMessage(e));
            update.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
        }
        groupCreateTaskRecordService.updateById(update);
    }

    private void completeTask(Long taskId) {
        String cacheKey = String.format(GroupCreateTaskServiceImpl.cacheKey, taskId);
        redisTemplate.delete(cacheKey);
        GroupCreateTask update = new GroupCreateTask();
        update.setId(taskId);
        update.setStatus(4);
        update.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
        this.updateById(update);
    }

    private void generateRecords(GroupCreateTask createTask) {
        //
        List<Long> deviceUniqueIds = JSON.parseArray(createTask.getDeviceUniqueId(), Long.class);
        //
        String groupName = createTask.getGroupName();
        Integer groupNum = createTask.getGroupNum();
        //
        Integer startNo = ObjectUtils.defaultIfNull(createTask.getStartNo(), 1);
        Integer intervalLeft = createTask.getIntervalLeft();
        Integer intervalRight = createTask.getIntervalRight();

        int now = (int) (System.currentTimeMillis() / 1000L);
        List<GroupCreateTaskRecord> records = Lists.newArrayList();
        //
        for (Long deviceUniqueId : deviceUniqueIds) {
            //
            int preTime = now;
            for (int i = 1; i <= groupNum; i++) {
                String randomStr = RandomUtil.randomString(4);
                //
                String finalGroupName = groupName.replace("[随机字符]", randomStr).replace("[自增编号]", startNo.toString());

                GroupCreateTaskRecord taskRecord = new GroupCreateTaskRecord();
                taskRecord.setId(IdUtil.getSnowflakeNextId());
                taskRecord.setMerId(createTask.getMerId());
                taskRecord.setDeviceUniqueId(deviceUniqueId);
                taskRecord.setStatus(0);
                taskRecord.setSort(i);
                taskRecord.setLast(i == groupNum ? 1 : 0);
                taskRecord.setTaskId(createTask.getId());
                taskRecord.setPublishTime(preTime);
                taskRecord.setGroupMembers(createTask.getGroupMembers());
                taskRecord.setGroupName(finalGroupName);
                taskRecord.setCreateTime(now);
                taskRecord.setUpdateTime(now);

                records.add(taskRecord);
                startNo++;
                preTime += RandomUtil.randomInt(intervalLeft, intervalRight);
            }
        }
        groupCreateTaskRecordService.saveBatch(records);
    }
}

